/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

import path from 'path';

import { expect } from '@jest/globals';
import * as execa from 'execa';
import fse from 'fs-extra';

import { getJson5Obj } from '../../../../src/utils/json-util';
import { initExecuteCommand, runHvigorAsync, runHvigorFailAsync } from '../../common/common';
import { commonConfig } from '../../plugins/common-config';
import { buildServiceCard, cleanTarget } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { Project } from '../../plugins/project-builder/models/project-models';
import { ICaseRecord } from '../../plugins/report-builder/report-models';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API11,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: {
    [ModuleTemplateType.SharedLibrary]: 1,
    [ModuleTemplateType.StaticLibrary]: 1,
  },
};
const commands = initExecuteCommand({
  mode: 'module',
  product: 'default',
  tasks: 'assembleHap',
});

/**
 * oh-package.json5添加依赖
 */
async function addOhPkgDependencies(modulePath: string, depModuleName: string, depModulePath: string, record: ICaseRecord) {
  const jsonPath = path.resolve(modulePath, 'oh-package.json5');
  const jsonData = getJson5Obj(jsonPath);
  jsonData.name = path.basename(modulePath);
  if (depModuleName === '' || depModuleName.length <= 0) {
    await fse.writeFile(jsonPath, JSON.stringify(jsonData,null,2), 'utf-8');
    return;
  }
  jsonData.dependencies[depModuleName] = `file:${depModulePath}`;
  await fse.writeFile(jsonPath, JSON.stringify(jsonData,null,2), 'utf-8');
  // 执行ohpm install
  const install = await execa.command(commonConfig.ohpmInstallCommand, {
    cwd: modulePath
  });
  record.addStep(`${depModuleName} install`, install);
}

const testfun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRoot = project.projectRootPath();
  const entryPath = project.getModule('entry').moduleRootPath();
  const ohPackagePath = path.resolve(entryPath, 'oh-package.json5');
  const ohPackageJson = getJson5Obj(ohPackagePath);
  await fse.writeFile(ohPackagePath, JSON.stringify(ohPackageJson));

  // 给模块添加服务卡片
  await buildServiceCard(entryPath, 'HelloWorld');
  const widgetCardPath: string = path.resolve(entryPath, 'src/main/ets/widget/pages/WidgetCard.ets');
  const widgetCardBuff: Buffer = await fse.readFile(widgetCardPath);
  const widgetCardStr: string = widgetCardBuff.toString();
  // ohpm install
  await addOhPkgDependencies(entryPath, 'shareLibrary', '../shareLibrary', record);
  await fse.writeFile(widgetCardPath, `import { add } from 'shareLibrary';\nadd(1, 2);\n${widgetCardStr}`);
  const result = await runHvigorFailAsync(projectRoot, commands);
  record.addStep('卡片中直接依赖hsp', result);
  expect(result.stderr).toContain('BUILD FAILED');
  expect(result.stderr).toContain('The service widget file contains one or more references to HSPs: \'shareLibrary\'');
  await cleanTarget(project);
  // 间接依赖
  await testIndirectDeptHsp(project, record, widgetCardPath, widgetCardStr);
  await testByteHar(project, record);
};

/**
 * 测试间接依赖
 */
const testIndirectDeptHsp = async (project: Project, record: ICaseRecord, widgetCardPath: string, widgetCardStr: string) => {
  const entryPath = project.getModule('entry').moduleRootPath();
  const harRootPath = project.getModule('staticLibrary').moduleRootPath();
  const harMainPage = path.resolve(harRootPath, 'src/main/ets/components/mainpage/MainPage.ets');
  const harMainPageStr = fse.readFileSync(harMainPage).toString();
  // entry依赖har，har依赖hsp
  await addOhPkgDependencies(harRootPath, 'shareLibrary', '../shareLibrary', record);
  await addOhPkgDependencies(entryPath, 'staticLibrary', '../staticLibrary', record);

  await fse.writeFile(
    harMainPage,
    `import { add } from 'shareLibrary';\n${harMainPageStr.replace('\'Hello World\'', '\'Hello World\' + add(1, 2)')}`,
  );
  await fse.writeFile(widgetCardPath, `import { MainPage } from 'staticLibrary';\nMainPage();\n${widgetCardStr}`);
  const result1 = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('卡片依赖har，har依赖hsp', result1);
  expect(result1.stderr).toContain('BUILD FAILED');
  expect(result1.stderr).toContain('The service widget file contains one or more references to HSPs: \'shareLibrary\'');
  await cleanTarget(project);
};

/**
 * 测试间接依赖字节码har
 */
async function testByteHar(project:Project, record:ICaseRecord) {
  const projectRoot = project.projectRootPath();
  const entryRoot = project.getModule('entry').moduleRootPath();
  const hspRootPath = project.getModule('shareLibrary').moduleRootPath();
  const harRootPath = project.getModule('staticLibrary').moduleRootPath();
  const hspCmd = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHsp',
  });
  const harCmd = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHar',
  });
  // 构建hsp
  const result = await runHvigorAsync(projectRoot, hspCmd);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');
  const outputHspPath = path.resolve(hspRootPath, 'build/default/outputs/default/shareLibrary.har');
  fse.copyFileSync(outputHspPath, path.resolve(harRootPath, 'shareLibrary.har'));
  // har依赖hsp
  await addOhPkgDependencies(harRootPath, 'shareLibrary', 'shareLibrary.har', record);

  // 将字节码har配置到entry
  // 构建har
  const result1 = await runHvigorAsync(projectRoot, harCmd);
  expect(result1.stdout).toContain('BUILD SUCCESSFUL');
  const outputHsrPath = path.resolve(harRootPath, 'build/default/outputs/default/staticLibrary.har');
  fse.copyFileSync(outputHsrPath, path.resolve(entryRoot, 'staticLibrary.har'));
  // entry依赖har
  await addOhPkgDependencies(entryRoot, 'staticLibrary', 'staticLibrary.har', record);
  const result2 = await runHvigorFailAsync(project.projectRootPath(), commands);
  record.addStep('卡片依赖字节码har，har依赖hsp', result2);
  expect(result2.stderr).toContain('BUILD FAILED');
  expect(result2.stderr).toContain('The service widget file contains one or more references to HSPs: \'shareLibrary\'');
  await cleanTarget(project);
}

TestCaseBuilder.builder()
  .caseName('AR20241025276283')
  .description('卡片引用HSP编译构建拦截报错')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testfun)
  .load();
